<?php
namespace Admin\Controller;

use Admin\Enums\ImageType;
use Think\Controller;
use OSS\OssClient;
use OSS\Core\OssException;
use Admin\Service\ImageService;
use OSS\Model\PrefixInfo;
use OSS\Model\ObjectInfo;
Vendor('OSS.autoload');
 // 引入文件
/**
 * oss上传
 * 
 * @author Administrator
 *        
 */
class OssController extends AdminController
{

    public function _initialize()
    {
        $this->accessKeyId = C('OSS.accessKeyId');
        $this->accessKeySecret = C('OSS.accessKeySecret');
        $this->endpoint = C('OSS.endpoint');
        $this->bucket = C('OSS.bucket')['img'];
        $this->ossDomain = C('OSS.ossDomain')['img'];

        try {
            $this->oss = new OssClient($this->accessKeyId, $this->accessKeySecret, $this->endpoint);
        } catch (OssException $e) {
            print $e->getMessage();
        }
        parent::_initialize();
    }

    /**
     * 上传文件到本地
     * @param array $file
     * @param unknown $uploads_dir
     * @return string
     */
    public function uploadFiles()
    {
        $file = $_FILES['images'];
        $uploads_dir = RUNTIME_PATH."Uploads";
        $this->mkdirs($uploads_dir);
        $tmp_name = $file["tmp_name"];
        $name = $file["name"];
        move_uploaded_file($tmp_name, $uploads_dir . '/' . $name);
        $img_url = $uploads_dir . "/" . $name;
        $response = array("img_url"=>$img_url);
        $this->success($response);
    }

    /**
    * 上传谱单图片到aliyun
    */
    public function uploadScore($param)
    {
        $this->bucket = C('OSS.bucket')['score-headimg'];
        $this->ossDomain = C('OSS.ossDomain')['score-headimg'];
        $image_urls = $param['image_urls'];
        foreach ($image_urls as $image_url) {
            $file = explode( '/', $image_url );
            $filename = $file[count( $file ) - 1];
            //step-2: 上传图片到阿里云服务器
            try {
            $data = $this->oss->uploadFile($this->bucket, "01AdminImg" . "/" . $this->generateFileName($image_url), $image_url);
            unlink($image_url);

            //step-3: 上传成功后把图片信息保存到数据库
            $image = array(
                "name"  =>  $filename,
                "url"   =>  $data['oss-request-url'],
                "img_type"  =>  ImageType::$SCORE,
            );

            $imageService = new ImageService();
            $image_id[] = $imageService->save($image);

            } catch (OssException $e) {
                return $e->getErrorMessage();
            }
        }
        return $image_id;
    }

    /**
     * 上传曲谱图片到aliyun
     */
    public function uploadSheet($param)
    {
        $image_urls = $param['image_urls'];
        foreach ($image_urls as $image_url) {
            $file = explode('/', $image_url);
            $filename = $file[count($file)-1];
            try {

                //step-2: 上传图片到阿里云服务器
                $data = $this->oss->uploadFile($this->bucket, $param['name'] . "/" . $this->generateFileName($image_url), $image_url);
                unlink($image_url);

                //step-3: 上传成功后把图片信息保存到数据库
                $image = array(
                    "name"  =>  $filename,
                    "url"   =>  $data['oss-request-url'],
                    "img_type"  =>  ImageType::$SHEET,
                );

                $imageService = new ImageService();
                $image_id[] = $imageService->save($image);
            } catch (OssException $e) {
                return $e->getErrorMessage();
            }
        }
        return $image_id;
    }
    
    /**
     * 将文件内容md5加密，生成文件名
     * @param unknown $filePath
     */
    private function generateFileName($filePath){
        header('Content-type:text/html;charset=utf-8');
        //读取图片文件，转换成base64编码格式
        return md5(file_get_contents($filePath)).'.'.$this->get_extension($filePath);
    }

    /**
     * 获取文件后缀名
     * @param unknown $file
     * @return mixed
     */
    private function get_extension($file)
    {
        return pathinfo($file, PATHINFO_EXTENSION);
    }

    
    function mkdirs($dir, $mode = 0777)
    {
        if (is_dir($dir) || @mkdir($dir, $mode)) return TRUE;
        if (!mkdirs(dirname($dir), $mode)) return FALSE;
        return @mkdir($dir, $mode);
    }

    /**
     * 将未写入数据库的oss文件写入数据库
     */
    public function updateSheetData()
    {
        $prefix = '';
        $delimiter = '/';
        $nextMarker = '';
        $maxkeys = 1000;

        
        
        while (true) {
            $dirLists = [];
            $options = [
                'delimiter' => '/',
                'prefix'    => '',
                'max-keys'  => 1,
                'marker'    => '',
            ];

            try {
                $listObjectInfo = $this->oss->listObjects($this->bucket, $options);
            } catch (OssException $e) {
                printf($e->getMessage() . "\n");
                return;
            }
            // 得到nextMarker，从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表
            $nextMarker = $listObjectInfo->getNextMarker();
            $listPrefix = $listObjectInfo->getPrefixList(); //一页的结果
            $listObject = $listObjectInfo->getObjectList();
            
            foreach ($listPrefix as $item) {
                $dirLists[] = $this->prefixInfoParse( $item );//oss文件夹索引
            }
            
            //遍历获取dirname
            foreach ($dirLists as $val) {
                $dirName[] = substr($val,0,strlen($val)-1);
            }
            //获取的结果到数据库中查询
            $map = array(
                'name' => array('in', $dirName)
            );

            $model = M('Sheet');
            $sheet = $model->field('name')->where($map)->select();
            
            if (!empty($sheet)) {
                foreach ($sheet as $value) {
                    $sheetList[] = $value['name'];
                }

                //比对数据结果，获取在oss未写入数据库的数据
                $unwriteData = array_diff($dirName, $sheetList);
                foreach ($unwriteData as $val) {
                    $unwriteName[] = $val;  //文件名
                    $unwriteDir[] = $val.'/';  //prefix索引
                }
                unset($unwriteData);
                //遍历获取未写入数据库文件夹下的文件
                if (!empty($unwriteDir)) {
                    foreach ($unwriteDir as $key => $val) {
                        $file_prefix = $val;
                        $delimiter = '/';
                        $file_nextMarker = '';
                        $file_maxkeys = 10;
                        while (true) {
                            $options = [
                                'delimiter' => $delimiter,
                                'prefix' => $file_prefix,
                                'max-keys' => $file_maxkeys,
                                'marker' => $file_nextMarker,
                            ];
                            try {
                                $listObjectInfo = $this->oss->listObjects( $this->bucket, $options );
                            } catch (OssException $e) {
                                printf( $e->getMessage() . "\n" );
                                return;
                            }
                            
                            print_r($listObjectInfo);exit;
                            // 得到nextMarker，从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表
                            $file_nextMarker = $listObjectInfo->getNextMarker();
                            $listObject = $listObjectInfo->getObjectList();

                            if (empty($listObject)) {
                                $fileList[$key] = [];
                            }
                            foreach ($listObject as $item) {
                                $fileList[$key][] = $this->objectInfoParse( $item );
                            }

                            if ($file_nextMarker === '') {
                                break;
                            }
                        }
                    }

                    //写入数据
                    //1.写入曲谱数据
                    $sheetModel = M('Sheet');
                    foreach ($unwriteName as $key => $val) {
                        $sheetParam = array(
                            'name' => $val,
                            'creator' => 2,
                            'author_type' => 10
                        );
                        $sheetId = $sheetModel->add($sheetParam);
                        $sheetIds[$key] = $sheetId;
                    }

                    //2.将图片写入Image表
                    $imageModel = M('Image');
                    foreach ($fileList as $key1 => $item) { //曲谱内的图片
                        if (!empty($item)) {
                            foreach ($item as $num => $val) {
                                $imageParam = array(
                                    'name' => $num.'.'.substr($val, -3),
                                    'url' => 'https://'.$this->ossDomain.'/'.$val,
                                    'creator' => 2,
                                    'img_type' => 10
                                );
                                $imgId = $imageModel->add($imageParam);
                                $imgIds[$key1][] = $imgId;
                            }
                        } else { //若文件夹内无图片，则将sheet标记为is_null
                            $data = array(
                                'is_null' => 1
                            );
                            $sheetModel->where(array('id'=>$sheetIds[$key1]))->save($data);
                            $imgIds[$key1] = array();
                        }
                    }
                    //3.记录曲谱和图片关系
                    $imgSheetModel = M('ImageSheet');
                    foreach ($imgIds as $key2 => $imgId) {
                        if (!empty($imgId)) {
                            foreach ($imgId as $id) {
                                $imgSheetParam[] = array(
                                    'sheet_id' => $sheetIds[$key2],
                                    'image_id' => $id,
                                    'creator' => 2
                                );
                            }
                        }
                    }
                    $res = $imgSheetModel->addAll($imgSheetParam);
                }
                unset($sheetList);
                unset($sheetIds);
                unset($imgIds);
                unset($imgSheetParam);
                unset($unwriteName);
                unset($unwriteDir);
            }

            //获取已写入数据库的imgurl
            foreach ($dirLists as $key3 => $val) {
                $file_prefix = $val;
                $delimiter = '/';
                $file_nextMarker = '';
                $file_maxkeys = 50;
                while (true) {
                    $options = [
                        'delimiter' => $delimiter,
                        'prefix' => $file_prefix,
                        'max-keys' => $file_maxkeys,
                        'marker' => $file_nextMarker,
                    ];
                    try {
                        $listObjectInfo = $this->oss->listObjects( $this->bucket, $options );
                    } catch (OssException $e) {
                        printf( $e->getMessage() . "\n" );
                        return;
                    }
                    // 得到nextMarker，从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表
                    $file_nextMarker = $listObjectInfo->getNextMarker();
                    $listObject = $listObjectInfo->getObjectList();

                    foreach ($listObject as $item) {
                        $imgName = $this->objectInfoParse($item);
                        $urls[] = 'https://'.$this->ossDomain.'/'.$imgName;
                    }

                    if ($file_nextMarker === '') {
                        break;
                    }
                }
            }
            $sheetModel = M('Sheet');
            $imageModel = M('Image');
            $imgSheetModel = M('ImageSheet');
            $map = array(
                'url' => array('in', $urls)
            );
            $checkUrl = $imageModel->where($map)->field('url')->group('url')->select();
            if (!empty($checkUrl)) {
                foreach ($checkUrl as $val) {
                    $wroteImgUrl[] = $val['url'];
                }
                //校验出未写入数据库的url
                $unwriteUrl = array_diff($urls,$wroteImgUrl);
                if (!empty($unwriteUrl)) {
                    //写入数据库
                    foreach ($unwriteUrl as $key => $val) {
                        $explodeUrl = explode( '/', $val );
                        $sheetName = $explodeUrl[3];
                        $sheetId = $sheetModel->where( array('name' => $sheetName) )->field( 'id' )->select();
                        if (!empty( $sheetId[0]['id'] )) {
                            $imgParam2 = array(
                                'name' => $explodeUrl[4],
                                'url' => $val,
                                'creator' => 2,
                                'img_type' => 10
                            );
                            $imgId = $imageModel->add($imgParam2);
                            $imgSheetParam2 = array(
                                'sheet_id' => $sheetId[0]['id'],
                                'image_id' => $imgId,
                                'creator'  => 2
                            );
                            $imgSheetId = $imgSheetModel->add($imgSheetParam2);
                        }
                    }
                    //释放内存
                    unset($dirName);
                    unset($dirLists);
                    unset($fileList);
                    unset($wroteImgUrl);
                }
            }

            if ($nextMarker === '') {
                echo "finished!";
                break;
            }
        }
    }

    /**
     * 获取马甲头像
     */
    public function getAliasImg()
    {
        $this->bucket = C('oss.bucket')['user-majia'];
        $this->ossDomain = C('oss.ossDomain')['user-majia'];
        $prefix = '马甲头像/';
        $delimiter = '/';
        $nextMarker = '';
        $maxkeys = 1000;

        while (true) {
            $dirLists = [];
            $options = [
                'delimiter' => '/',
                'prefix'    => $prefix,
                'max-keys'  => $maxkeys,
                'marker'    => $nextMarker,
            ];

            try {
                $listObjectInfo = $this->oss->listObjects($this->bucket, $options);
            } catch (OssException $e) {
                printf($e->getMessage() . "\n");
                return;
            }
            // 得到nextMarker，从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表
            $nextMarker = $listObjectInfo->getNextMarker();
            $listPrefix = $listObjectInfo->getPrefixList(); //一页的结果
            $listObject = $listObjectInfo->getObjectList();

            foreach ($listObject as $item) {
                $fileList[] = $this->objectInfoParse( $item );//oss文件夹索引
            }
            if ($nextMarker == '') {
                break;
            }
        }

        foreach ($fileList as $key => $filename) {
            $imgName = explode('/', $filename);
            $data[$key]['name'] = $imgName[1];
            $data[$key]['url'] = $this->ossDomain.'/'.$filename;
            $data[$key]['img_type'] = 30;
            $data[$key]['creator'] = 2;
            $data[$key]['create_time'] = date('Y-m-d H:i:s', '1503070215');
        }
        $model = M('Image');
        $res = $model->addAll($data);
        dump($res);
    }


    /**
     * 获取随机首图
     */
    public function getHeadImg()
    {
        $this->bucket = C('oss.bucket')['score-headimg'];
        $this->ossDomain = C('oss.ossDomain')['score-headimg'];
        $prefix = '01RandomImg/';
        $delimiter = '/';
        $nextMarker = '';
        $maxkeys = 1000;

        while (true) {
            $dirLists = [];
            $options = [
                'delimiter' => '/',
                'prefix'    => $prefix,
                'max-keys'  => $maxkeys,
                'marker'    => $nextMarker,
            ];

            try {
                $listObjectInfo = $this->oss->listObjects($this->bucket, $options);
            } catch (OssException $e) {
                printf($e->getMessage() . "\n");
                return;
            }
            // 得到nextMarker，从上一次listObjects读到的最后一个文件的下一个文件开始继续获取文件列表
            $nextMarker = $listObjectInfo->getNextMarker();
            $listPrefix = $listObjectInfo->getPrefixList(); //一页的结果
            $listObject = $listObjectInfo->getObjectList();

            foreach ($listObject as $item) {
                $fileList[] = $this->objectInfoParse( $item );//oss文件夹索引
            }
            if ($nextMarker == '') {
                break;
            }
        }

        foreach ($fileList as $key => $filename) {
            $imgName = explode('/', $filename);
            $data[$key]['name'] = $imgName[1];
            $data[$key]['url'] = $this->ossDomain.'/'.$filename;
            $data[$key]['img_type'] = 40;
            $data[$key]['creator'] = 2;
            $data[$key]['create_time'] = date('Y-m-d H:i:s', time());
        }
        $model = M('Image');
        $res = $model->addAll($data);
        dump($res);
    }


    /* 解析 prefixInfo 类 */
    private function prefixInfoParse(PrefixInfo $prefixInfo){
        return $prefixInfo->getPrefix();
    }
    /* 解析 objectInfo 类 */
    private function objectInfoParse(ObjectInfo $objectInfo) {
        return $objectInfo->getKey();
            //'name'      => $objectInfo->getKey(),
            //'size'      => $objectInfo->getSize(),
            //'update_at' => $objectInfo->getLastModified(),
    }
}
